<?php

namespace WebmanGrpc\Event;

/**
 * 生命周期事件管理器
 * 
 * 提供生命周期事件的钩子机制
 */
class LifecycleEventManager
{
    /**
     * 单例实例
     * @var LifecycleEventManager|null
     */
    protected static ?LifecycleEventManager $instance = null;
    
    /**
     * 生命周期钩子
     * @var array
     */
    protected array $hooks = [];
    
    /**
     * 获取单例实例
     * 
     * @return LifecycleEventManager 生命周期事件管理器实例
     */
    public static function getInstance(): LifecycleEventManager
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        
        return self::$instance;
    }
    
    /**
     * 私有构造函数，防止直接实例化
     */
    protected function __construct()
    {
        // 初始化配置
    }
    
    /**
     * 克隆方法，防止克隆
     */
    private function __clone()
    {
        // 防止克隆
    }
    
    /**
     * 添加生命周期钩子
     * 
     * @param string $event 生命周期事件
     * @param callable $callback 回调函数
     * @param int $priority 优先级
     * @return void
     */
    public function addHook(string $event, callable $callback, int $priority = 0): void
    {
        if (!isset($this->hooks[$event])) {
            $this->hooks[$event] = [];
        }
        
        $this->hooks[$event][] = [
            'callback' => $callback,
            'priority' => $priority,
        ];
        
        // 按优先级排序
        usort($this->hooks[$event], function ($a, $b) {
            return $b['priority'] - $a['priority'];
        });
    }
    
    /**
     * 移除生命周期钩子
     * 
     * @param string $event 生命周期事件
     * @param callable $callback 回调函数
     * @return void
     */
    public function removeHook(string $event, callable $callback): void
    {
        if (!isset($this->hooks[$event])) {
            return;
        }
        
        $this->hooks[$event] = array_filter($this->hooks[$event], function ($item) use ($callback) {
            return $item['callback'] !== $callback;
        });
    }
    
    /**
     * 触发生命周期事件
     * 
     * @param string $event 生命周期事件
     * @param mixed ...$args 参数
     * @return void
     */
    public function trigger(string $event, ...$args): void
    {
        if (!isset($this->hooks[$event])) {
            return;
        }
        
        foreach ($this->hooks[$event] as $hook) {
            try {
                call_user_func_array($hook['callback'], $args);
            } catch (\Exception $e) {
                // 忽略钩子异常，避免影响其他钩子
                error_log("Lifecycle hook error for event '{$event}': " . $e->getMessage());
            }
        }
    }
    
    /**
     * 检查是否有生命周期钩子
     * 
     * @param string $event 生命周期事件
     * @return bool 是否有钩子
     */
    public function hasHooks(string $event): bool
    {
        return !empty($this->hooks[$event]);
    }
    
    /**
     * 获取生命周期钩子
     * 
     * @param string $event 生命周期事件
     * @return array 生命周期钩子
     */
    public function getHooks(string $event): array
    {
        return $this->hooks[$event] ?? [];
    }
    
    /**
     * 清空生命周期钩子
     * 
     * @param string|null $event 生命周期事件，为null时清空所有钩子
     * @return void
     */
    public function clearHooks(?string $event = null): void
    {
        if ($event === null) {
            $this->hooks = [];
        } else {
            unset($this->hooks[$event]);
        }
    }
    
    /**
     * 获取所有生命周期事件
     * 
     * @return array 生命周期事件列表
     */
    public function getAllEvents(): array
    {
        return array_keys($this->hooks);
    }
    
    /**
     * 获取统计信息
     * 
     * @return array 统计信息
     */
    public function getStats(): array
    {
        $stats = [
            'total_events' => count($this->hooks),
            'total_hooks' => 0,
            'events' => [],
        ];
        
        foreach ($this->hooks as $event => $hooks) {
            $hookCount = count($hooks);
            $stats['total_hooks'] += $hookCount;
            $stats['events'][$event] = $hookCount;
        }
        
        return $stats;
    }
}